home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / runtime / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-03  |  6.0 KB  |  252 lines  |  [TEXT/R*ch]

  1. /* Start-up code */
  2.  
  3. #include <stdio.h>
  4. #include <fcntl.h>
  5. #include <sys/types.h>
  6. #include "version.h"
  7. #include "alloc.h"
  8. #include "exec.h"
  9. #include "fail.h"
  10. #include "gc.h"
  11. #include "globals.h"
  12. #include "intext.h"
  13. #include "io.h"
  14. #include "misc.h"
  15. #include "mlvalues.h"
  16. #include "stacks.h"
  17. #include "sys.h"
  18. #include "debugcom.h"
  19.  
  20. #ifndef macintosh
  21. #ifdef __STDC__
  22. #include <stdlib.h>
  23. #else
  24. extern char *getenv ();
  25. #endif /* __STDC__ */
  26. #endif /* not macintosh */
  27.  
  28. extern value interprete();
  29.  
  30. #ifndef O_BINARY
  31. #define O_BINARY 0
  32. #endif
  33.  
  34. header_t first_atoms[256];
  35. code_t start_code;
  36. asize_t code_size;
  37.  
  38. static void init_atoms()
  39. {
  40.   int i;
  41.   for(i = 0; i < 256; i++) first_atoms[i] = Make_header(0, i, White);
  42. }
  43.  
  44. static unsigned long read_size(p)
  45.      unsigned char * p;
  46. {
  47.   return ((unsigned long) p[0] << 24) + ((unsigned long) p[1] << 16) +
  48.          ((unsigned long) p[2] << 8) + p[3];
  49. }
  50.  
  51. #define FILE_NOT_FOUND (-1)
  52. #define TRUNCATED_FILE (-2)
  53. #define BAD_MAGIC_NUM (-3)
  54.  
  55. static int read_trailer(fd, trail)
  56.      int fd;
  57.      struct exec_trailer * trail;
  58. {
  59.   char buffer[TRAILER_SIZE];
  60.  
  61.   lseek(fd, (long) -TRAILER_SIZE, 2);
  62.   if (read(fd, buffer, TRAILER_SIZE) < TRAILER_SIZE) return TRUNCATED_FILE;
  63.   trail->code_size = read_size(buffer);
  64.   trail->data_size = read_size(buffer+4);
  65.   trail->symbol_size = read_size(buffer+8);
  66.   trail->debug_size = read_size(buffer+12);
  67.   trail->magic = read_size(buffer+16);
  68.   if (trail->magic == EXEC_MAGIC) return 0; else return BAD_MAGIC_NUM;
  69. }
  70.  
  71. extern char * searchpath();
  72.  
  73. int attempt_open(name, trail, do_open_script)
  74.      char ** name;
  75.      struct exec_trailer * trail;
  76.      int do_open_script;
  77. {
  78.   char * truename;
  79.   int fd;
  80.   int err;
  81.   char buf [2];
  82.  
  83.   truename = searchpath(*name);
  84.   if (truename == 0) truename = *name; else *name = truename;
  85.   fd = open(truename, O_RDONLY | O_BINARY);
  86.   if (fd == -1) return FILE_NOT_FOUND;
  87.   if (!do_open_script){
  88.     err = read (fd, buf, 2);
  89.     if (err < 2) return TRUNCATED_FILE;
  90.     if (buf [0] == '#' && buf [1] == '!') return BAD_MAGIC_NUM;
  91.   }
  92.   err = read_trailer(fd, trail);
  93.   if (err != 0) { close(fd); return err; }
  94.   return fd;
  95. }
  96.  
  97. /* Invocation of camlrun: 4 cases.
  98.  
  99.    1.  runtime + bytecode
  100.        user types:  camlrun [options] bytecode args...
  101.        arguments:  camlrun [options] bytecode args...
  102.  
  103.    2.  bytecode script
  104.        user types:  bytecode args...
  105.    2a  (kernel 1) arguments:  camlrun ./bytecode args...
  106.    2b  (kernel 2) arguments:  bytecode bytecode args...
  107.  
  108.    3.  concatenated runtime and bytecode
  109.        user types:  composite args...
  110.        arguments:  composite args...
  111.  
  112. Algorithm:
  113.   1-  If argument 0 is a valid byte-code file that does not start with #!,
  114.       then we are in case 3 and we pass the same command line to the
  115.       Caml Light program.
  116.   2-  In all other cases, we parse the command line as:
  117.         (whatever) [options] bytecode args...
  118.       and we strip "(whatever) [options]" from the command line.
  119.  
  120. */
  121.  
  122. #ifdef HAS_UI
  123. int caml_main(argc, argv)
  124. #else
  125. int main(argc, argv)
  126. #endif
  127.      int argc;
  128.      char * argv[];
  129. {
  130.   int fd;
  131.   struct exec_trailer trail;
  132.   int i;
  133.   struct longjmp_buffer raise_buf;
  134.   struct channel * chan;
  135.   int verbose_init = 0, percent_free_init = Percent_free_def;
  136.   long minor_heap_init = Minor_heap_def, heap_chunk_init = Heap_chunk_def;
  137.   char * debugger_address = NULL;
  138. #ifdef MSDOS
  139.   extern char ** check_args();
  140.   argv = check_args(argv);
  141. #endif
  142.  
  143. #ifdef DEBUG
  144.   verbose_init = 1;
  145. #endif
  146.  
  147.   i = 0;
  148.   fd = attempt_open(&argv[0], &trail, 0);
  149.  
  150.   if (fd < 0) {
  151.  
  152.     for(i = 1; i < argc && argv[i][0] == '-'; i++) {
  153.       switch(argv[i][1]) {
  154. #ifdef DEBUG
  155.       case 't': {
  156.         extern int trace_flag;
  157.         trace_flag = 1;
  158.         break;
  159.       }
  160. #endif
  161.       case 'v':
  162.         verbose_init = 1;
  163.         break;
  164.       case 'V':
  165.         fprintf(stderr, "The Caml Light runtime system, version %s\n",
  166.                 VERSION);
  167.         exit(0);
  168.       default:
  169.         fatal_error_arg("Unknown option %s.\n", argv[i]);
  170.       }
  171.     }
  172.  
  173.     if (argv[i] == 0)
  174.       fatal_error("No bytecode file specified.\n");
  175.  
  176.     fd = attempt_open(&argv[i], &trail, 1);
  177.  
  178.     switch(fd) {
  179.     case FILE_NOT_FOUND:
  180.       fatal_error_arg("Fatal error: cannot find file %s\n", argv[i]);
  181.       break;
  182.     case TRUNCATED_FILE:
  183.     case BAD_MAGIC_NUM:
  184.       fatal_error_arg(
  185.         "Fatal error: the file %s is not a bytecode executable file\n",
  186.         argv[i]);
  187.       break;
  188.     }
  189.   }
  190.  
  191.   /* Runtime options.  The option letter is the first letter of the
  192.      last word of the ML name of the option (see [lib/gc.mli]). */
  193.  
  194.   { char *opt = getenv ("CAMLRUNPARAM");
  195.     if (opt != NULL){
  196.       while (*opt != '\0'){
  197.     switch (*opt++){
  198.     case 's': sscanf (opt, "=%ld", &minor_heap_init); break;
  199.     case 'i': sscanf (opt, "=%ld", &heap_chunk_init); break;
  200.     case 'o': sscanf (opt, "=%d", &percent_free_init); break;
  201.     case 'v': sscanf (opt, "=%d", &verbose_init); break;
  202.     }
  203.       }
  204.     }
  205.   }
  206.  
  207. #ifdef HAS_SOCKETS
  208.   if (debugger_address == NULL)
  209.     debugger_address = getenv("CAML_DEBUG_SOCKET");
  210. #endif
  211.  
  212.   if (setjmp(raise_buf.buf) == 0) {
  213.  
  214.     external_raise = &raise_buf;
  215.  
  216.     init_gc (minor_heap_init, heap_chunk_init, percent_free_init,
  217.          verbose_init);
  218.     init_stacks();
  219.     init_atoms();
  220.  
  221.     lseek(fd, - (long) (TRAILER_SIZE + trail.code_size + trail.data_size
  222.                         + trail.symbol_size + trail.debug_size), 2);
  223.  
  224.     code_size = trail.code_size;
  225.     start_code = (code_t) stat_alloc(code_size);
  226.     if (read(fd, (char *) start_code, code_size) != code_size)
  227.       fatal_error("Fatal error: truncated bytecode file.\n");
  228.  
  229. #if defined(BIG_ENDIAN) && !defined(ALIGNMENT)
  230.     fixup_endianness(start_code, code_size);
  231. #endif
  232.  
  233.     chan = open_descr(fd);
  234.     global_data = intern_val(chan);
  235.     modify(&Field(global_data, GLOBAL_DATA), global_data);
  236.     close_in(chan);
  237.  
  238.     sys_init(argv + i);
  239.     if (debugger_address != NULL) debugger_init(debugger_address);
  240.     interprete(start_code);
  241.     sys_exit(Val_int(0));
  242.  
  243.   } else {
  244.  
  245.     if (exn_bucket == Atom(OUT_OF_MEMORY_EXN))
  246.       fatal_error ("Fatal error: out of memory.\n");
  247.     else
  248.       fatal_error ("Fatal error: uncaught exception.\n");
  249.   }
  250. }
  251.  
  252.